from fuzzywuzzy import fuzz
import configs
from template.singleton import Singleton
from utils import service_functions
from .numbers_decoder import Numbers
from .wrapper_decoders_func import Wrapper_decoders

# from api import obj_class_api

from .decoders import Decoders

# from write_stream import Control_messages
# obj_decoders = Wrapper_decoders()
# obj_numbers = Numbers()


class Tags_decoder(Decoders, Singleton):
    def __init__(self) -> None:
        super().__init__()
        self.numbers = Numbers()

    def set_control_mess(self, obj_control_messages) -> None:
        # super().__init__()
        self.obj_control_messages = obj_control_messages

    def __recognition_marks_tag(
        self, cmd_str_tags: str, name_func: str = "", tags_all_list: list = []
    ) -> dict:
        if len(tags_all_list) == 0 and len(name_func) == 0:
            if configs.cmds["metka"]:
                tags_all_list = configs.cmds["metka"]
            else:
                return {}
        elif name_func:
            if "tags_list" in configs.cmds_void[name_func]["tags"]["tags"]:
                if len(configs.cmds_void[name_func]["tags"]["tags"]["tags_list"]) != 0:
                    tags_all_list = configs.cmds_void[name_func]["tags"]["tags"][
                        "tags_list"
                    ]
                else:
                    return {}
            else:
                # raise Exception('I know Python!')
                return {}
        cmd_str_tags = service_functions.error_correction(
            cmd_str_tags, tags_all_list, name_err=2
        )
        cmd_list_tags = cmd_str_tags.split(" ")
        tags_key = []
        tags_values = []
        index_old = -1
        print(cmd_list_tags)
        for index, value in enumerate(cmd_list_tags):
            if value in tags_all_list:
                if index_old != -1:
                    tags_key.append(cmd_list_tags[index])
                    tags_values.append(" ".join(cmd_list_tags[index_old + 1 : index]))
                else:
                    tags_key.append(cmd_list_tags[index])
                if index == index_old + 1 and index_old != -1:
                    return {}
                index_old = index
            elif index == len(cmd_list_tags) - 1:
                tags_values.append(
                    " ".join(cmd_list_tags[index_old + 1 : len(cmd_list_tags)])
                )
        print({"tags": tags_key, "value": tags_values})
        return {"tags": tags_key, "value": tags_values}

    def translate_tags_str_in_int(self, tags: list) -> list:
        return self.numbers.number_activation_label(tags)

    # dec_activation_tags
    def activation_tags_value_in_int(self, str_tags, func: str = "") -> list:
        tags = self.__recognition_marks_tag(str_tags, func)
        # print(tags,"activation_tags")
        # print(tags)
        if len(tags) != 0:
            tags = tags["value"]
            tags = self.translate_tags_str_in_int(tags)
            return tags
        else:
            return []

    def dec_function_recognition_keys(self, cmd_str, func, tags, dict_words) -> dict:
        len_str_cmd = len(cmd_str)
        list_value = []
        list_key = []
        list_key_value = []
        if len_str_cmd != 0:
            par = 100 / len_str_cmd
            booleen = int(par + configs.PROBABILITY_CMD_CONST) <= 100
            if booleen:
                if len_str_cmd != 0:
                    for dict_names in dict_words:
                        for key in tags[dict_names]:
                            for value_str in tags[dict_names][key]:
                                service_functions.fuzz_word_cheek(len(value_str))
                                Levenshtein_d = fuzz.partial_ratio(cmd_str, value_str)
                                if Levenshtein_d >= configs.probability_cmd:
                                    if len(value_str) == 0:
                                        return {
                                            "key": list_key,
                                            "values": list_value,
                                            "key_value": list_key_value,
                                        }
                                    elif len(value_str) > 0:
                                        list_value.append(value_str)
                                        list_key.append(key)
                                        list_key_value.append(
                                            {key: dict_words[dict_names][key]}
                                        )
            else:
                for dict_names in dict_words:
                    for key in tags[dict_names]:

                        for value_str in tags[dict_names][key]:
                            service_functions.fuzz_word_cheek(len(value_str))
                            Levenshtein_d = fuzz.partial_ratio(cmd_str, value_str)
                            if Levenshtein_d >= configs.probability_cmd:
                                list_value.append(value_str)
                                list_key.append(key)
                                list_key_value.append(
                                    {key: dict_words[dict_names][key]}
                                )
                            else:
                                pass
        return {"key": list_key, "values": list_value, "key_value": list_key_value}


class Tags_wrapper(Singleton):
    def __init__(self) -> None:
        super().__init__()
        self.obj_tags_decoder = Tags_decoder()

    def set_control_mess(self, obj_control_messages) -> None:
        # super().__init__()
        self.obj_control_messages = obj_control_messages
        self.obj_tags_decoder.set_control_mess(self.obj_control_messages)

    def check_tags(self, func, tags):
        # Не активный !!!
        # Проверка колличества меток
        tags_kol = configs.cmds_void[func]["tags"]["tags"]["label_count"]
        if len(tags) != 0:
            return tags_kol == len(tags)
        else:
            return False

    def tags_params_tag_value_tag(self, cmd):
        # # Не активный !!!
        # ["tags","value","tags","value","tags","value","tags"]
        tags = self.obj_tags_decoder.__recognition_marks_tag(cmd)
        tags_value = tags["value"]
        tags_mark = tags["tags"]
        tags_all = []
        for x in range(len(tags_mark)):
            tags_all.append(tags_mark[x])
            tags_all.append(tags_value[x])
        return tags_all

    def loop_tags(self) -> dict:
        cmd_tags_value_all = []
        cmd_tags_mark_all = []
        menu_flag = ""
        self.obj_control_messages.message("Циклическая обработка меток")
        while "end" not in menu_flag:
            str_cmd = configs.stream_speech.get()
            cmd = self.obj_tags_decoder.search_key_cmd(str_cmd, "loop_make")
            if cmd in configs.cmds["loop_make"]:
                menu_flag = cmd
            if ("pause" not in menu_flag) and ("return_tags" not in menu_flag):
                cmd_tags = self.obj_tags_decoder.__recognition_marks_tag(str_cmd)
                cmd_tags_value_all = cmd_tags_value_all + cmd_tags["value"]
                cmd_tags_mark_all = cmd_tags_mark_all + cmd_tags["value"]
            elif "return_tags" in menu_flag:
                self.obj_control_messages.message(" ".join(cmd_tags_value_all))
            elif "clear" in menu_flag:
                cmd_tags_value_all.clear()
                cmd_tags_mark_all.clear()
                self.obj_control_messages.message("Метка очишена")
            else:
                pass
        return {"value": cmd_tags_value_all, "tags": cmd_tags_mark_all}

    def selection_tags(self, str_tags: str = "", func: str = "") -> list:
        # Если настройка в configs.tags_decoder_flag==True
        # Обработка меток в цикле
        if configs.tags_decoder_flag:
            return self.loop_tags()["value"]
        else:
            if len(str_tags) != 0:
                return self.obj_tags_decoder.activation_tags_value_in_int(str_tags)
            else:
                self.obj_control_messages.message("Скажите метки")
                return self.obj_tags_decoder.activation_tags_value_in_int(
                    service_functions.queue_voice_time_str_api(), func
                )


class Tags_key(Tags_decoder, Singleton):
    def set_control_mess(self, obj_control_messages) -> None:
        # super().__init__()
        self.obj_control_messages = obj_control_messages

    def cheek_key_or_tag(self, func, cmd_say):
        if "tags" in configs.cmds_void[func]["tags"]:
            return "tags"
        elif "key" in configs.cmds_void[func]["tags"]:
            return "key"
        else:
            return "error"

    def dict_word_searhc(self, cmd_str, func):
        where_to_look = configs.cmds_void[func]["tags"]["key"]["where_to_look"]
        if where_to_look == "local":
            tags = configs.cmds_void[func]["tags"]["key"]["label dictionary"]
            tags_dict_word = configs.cmds_void[func]["tags"]["key"]["dict_words"]
            return self.dec_function_recognition_keys(
                cmd_str, func, tags, tags_dict_word
            )
        else:
            return self.dec_function_recognition_keys(
                cmd_str,
                func,
                configs.cmds["dict_word_cmd_value"],
                configs.cmds["dict_words"],
            )
